package com.code.statistics.configs.cros;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

/**
 * 使用CORS，用于解决ajax跨域访问问题
 * <p>XMLHttpRequest对象实现的Ajax请求受到同源策略的限制，必须实现跨域。<br>
 * 然而JSONP就不一样，他没有这个限制，JSONP它的兼容性更好，在更加古老的浏览器中都可以运行，不需要XMLHttpRequest或ActiveX的支持；
 * 并且在请求完毕后可以通过调用callback的方式回传结果。<br>
 * 但是JSONP也有缺点，它只支持GET请求而不支持POST等其它类型的HTTP请求；它只支持跨域HTTP请求这种情况，
 * 不能解决不同域的两个页面之间如何进行JavaScript调用的问题</p>
 *
 * @author xiaoyaowang
 */
@Configuration
public class GlobalCorsConfig {

    @Bean
    public FilterRegistrationBean corsFilter() {
        //1.添加CORS配置信息
        CorsConfiguration config = new CorsConfiguration();
        //1) 允许的域,不要写*，否则cookie就无法使用了
        //指定允许其他域名访问
        config.addAllowedOrigin("*");
        //2) 是否发送Cookie信息，是否允许后续请求携带认证信息（cookies）,该值只能是true，否则不返回
        config.setAllowCredentials(true);
        //3) 允许的请求方式
        config.addAllowedMethod("OPTIONS");
        config.addAllowedMethod("HEAD");
        config.addAllowedMethod("GET");
        config.addAllowedMethod("PUT");
        config.addAllowedMethod("POST");
        config.addAllowedMethod("DELETE");
        config.addAllowedMethod("PATCH");
        //当我们使用put和delete请求时，浏览器会先发送option（预检）请求，不过有时候，你会发现并没有，这是后面我们会讲到缓存预检结果
        //预检结果缓存时间
        //预检请求:
        //与简单请求不同的是，option请求多了2个字段：
        //Access-Control-Request-Method：该次请求的请求方式
        //Access-Control-Request-Headers：该次请求的自定义请求头字段
        config.setMaxAge(3600L);
        // 4）允许的头信息，允许的请求头字段
        //这里有个注意点：Access-Control-Request-Method，Access-Control-Request-Headers返回的是满足服务器要求的所有请求方式，
        //请求头，不限于该次请求，我一次性告诉你了，别TM问我了
        config.addAllowedHeader("*");

        //2.添加映射路径，我们拦截一切请求
        UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
        configSource.registerCorsConfiguration("/**", config);

        //3.返回新的CorsFilter.
        //return new CorsFilter(configSource);

        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(configSource));
        //利用FilterRegistrationBean，将拦截器注册靠前,避免被其它拦截器首先执行
        bean.setOrder(0);
        return bean;
    }
}
